<?php

class stringStream {
    const PROTOCOL = 'string';
    const BLKSIZE = 4096;
    
    protected $dataPosition = null;
    protected $dataBuffer = null;
    protected $dataLength = null;
    private static $registered = false;
    
    private static function register() {
        stream_wrapper_register(stringStream::PROTOCOL, 'stringStream');
        self::$registered = true;
    }
    private static function registered() {
        if(self::$registered) {
            return true;
        }
        else {
            self::register();
            return true;
        }
    }
    
    public function stream_open($path, $mode, $options, &$openedPath) {
        $contextOptions = stream_context_get_options($this->context);
        if(!isset($contextOptions[self::PROTOCOL]['data'])) {
            return false;
        }
        $this->dataBuffer = $contextOptions[self::PROTOCOL]['data'];
        $this->dataLength = mb_strlen($this->dataBuffer);
        $this->dataPosition = 0;
        return true;
    }
    
    public function stream_read($count) {
        $retrieve = substr($this->dataBuffer, $this->dataPosition, $count);
        $this->dataPosition += mb_strlen($retrieve);
        return $retrieve;
    }
    public function stream_eof() {
        return ($this->dataPosition >= $this->dataLength ? true : false);
    }
    
    public function stream_tell() {
        return $this->dataPosition;
    }
    
    public function stream_stat() {
        $registry = Registry::GetInstance();
        $time = $registry->Get('currentTime');
        $stats = array(3 => 1, 7 => $this->dataLength, 8 => $time, 9 => $time, 10 => $time,
                        11 => self::BLKSIZE, 12 => ceil($this->dataLength / self::BLKSIZE));
        $fields = array(3 => 'nlink', 7 => 'size', 8 => 'atime', 9 => 'mtime', 10 => 'ctime',
                         11 => 'blksize', 12 => 'blocks');
        foreach($stats as $key => $stat) {
            $output[$key] = $stat;
            $output[$fields[$key]] = $stat;
        }
        return $output;
    }
    
    static private function genURL() {
        return self::PROTOCOL . '://';
    }
    
    static private function genContext($dataBuffer) {
        return stream_context_create(array(self::PROTOCOL => array('data' => $dataBuffer)));
    }
    
    static public function open($dataBuffer) {
        self::registered();
        return fopen(self::genURL(), 'r', false, self::genContext($dataBuffer));
    }
}